package com.base.springboot.starter.mybatisplus.service;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.base.springboot.starter.mybatisplus.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

/**
 * IService 二次封装实现类
 *
 * @author admin
 * @date 2020/5/19 AM10:15
 */
@Slf4j
public class GenericServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<BaseMapper<T>, T> implements GenericService<T> {

    @Autowired
    protected M baseMapper;

    /**
     * 获取当前Mapper
     *
     * @return 当前Mapper
     */
    @Override
    public M getBaseMapper() {
        return baseMapper;
    }

    /**
     * 根据 ID 查询
     *
     * @param id 主键ID
     * @return 实体对象
     */
    @Override
    public T getEntityById(Serializable id) {
        return this.getById(id);
    }

    /**
     * 查询列表
     *
     * @param queryWrapper 实体对象封装操作类 {@link QueryWrapper}
     * @return 实体对象列表
     */
    @Override
    public List<T> listEntity(Wrapper<T> queryWrapper) {
        return this.list(queryWrapper);
    }

    /**
     * 翻页查询
     *
     * @param page         翻页对象
     * @param queryWrapper 实体对象封装操作类 {@link QueryWrapper}
     * @return 实体对象分页对象
     */
    @Override
    public <E extends IPage<T>> E pageEntity(E page, Wrapper<T> queryWrapper) {
        return this.page(page, queryWrapper);
    }

    /**
     * 翻页查询
     *
     * @param page         翻页对象
     * @param queryWrapper 实体对象封装操作类 {@link QueryWrapper}
     * @return 实体对象列表
     */
    @Override
    public List<T> pageListEntity(Page<T> page, Wrapper<T> queryWrapper) {
        page.setSearchCount(false);
        IPage<T> iPage = this.page(page, queryWrapper);
        if (iPage != null) {
            return iPage.getRecords();
        }
        return null;
    }

    /**
     * 查询（根据ID 批量查询）
     *
     * @param idList 主键ID列表
     * @return 实体对象列表
     */
    @Override
    public List<T> listEntityByIds(Collection<? extends Serializable> idList) {
        return this.listByIds(idList);
    }

    /**
     * 插入一条记录（选择字段，策略插入）
     *
     * @param entity 实体对象
     * @return 插入结果，成功为true
     */
    @Override
    public Boolean saveEntity(T entity) {
        return this.save(entity);
    }

    /**
     * 根据 ID 删除
     *
     * @param id 主键ID
     * @return 删除结果，成功为true
     */
    @Override
    public Boolean removeEntityById(Serializable id) {
        return this.removeById(id);
    }

    /**
     * 根据 ID 选择修改
     *
     * @param entity 实体对象
     * @return 更新结果，成功为true
     */
    @Override
    public Boolean updateEntityById(T entity) {
        return this.updateById(entity);
    }

    /**
     * 获取实体属性对应数据库字段
     *
     * @param fieldName 数据库字段
     * @return 实体属性
     */
    @Override
    public String getColumnName(String fieldName) {
        // 获取实体对象信息
        TableInfo tableInfo = TableInfoHelper.getTableInfo(this.currentModelClass());

        QueryWrapperTransit queryWrapperTransit = new QueryWrapperTransit(new QueryWrapper(), this);
        queryWrapperTransit.eq("", "").like("", "");
        return this.getTableColumnName(tableInfo, fieldName);
    }

    /**
     * 分页计算起始值
     *
     * @param current
     * @param size
     * @return
     */
    @Override
    public long offset(long current, long size) {
        return current > 0L ? (current - 1L) * size : 0L;
    }

    /**
     * 通过对象属性查找数据库关联表字段
     *
     * @param property
     * @return
     */
    private String getTableColumnName(TableInfo tableInfo, String property) {
        if (tableInfo != null
                && tableInfo.getFieldList() != null
                && tableInfo.getFieldList().size() > 0) {
            if (StringUtil.compareObject(tableInfo.getKeyProperty(), property)) {
                return tableInfo.getKeyColumn();
            } else {
                for (TableFieldInfo field : tableInfo.getFieldList()) {
                    if (StringUtil.compareObject(field.getProperty(), property)) {
                        return field.getColumn();
                    }
                }
            }
        }
        return null;
    }
}